Skip to main content

IPTABLES

iptables is a user-space command-line tool used to configure Linux kernel packet filtering through the Netfilter framework. It controls how inbound, outbound, and forwarded traffic is handled by defining rules that match packets and apply actions such as accept, drop, reject, log, or jump to another chain.

iptables is widely used on Linux servers because it is powerful, scriptable, and deeply integrated with the kernel. Many higher-level firewall tools (such as UFW) translate their configurations into underlying iptables rules.

Scope

This page focuses on understanding core iptables concepts, reading existing rule sets, and applying safe patterns for common server use cases.

Compatibility note

On many modern distributions, nftables is the preferred firewall framework, and iptables commands may be implemented via compatibility layers (for example, iptables-nft). The syntax remains useful for reading legacy systems and understanding how higher-level tooling works.

Where iptables Fits in the Linux Networking Stack

Netfilter is built into the Linux kernel. iptables is one way to configure Netfilter rules.

Core Concepts

Tables

Tables group rules by purpose.

TablePurposeCommon Use
---
filterPacket filtering (allow/deny)Host firewall rules
natNetwork Address TranslationPort forwarding, masquerading
manglePacket modificationAdvanced routing/QoS
rawConnection tracking exemptionsSpecialized performance cases
securitySELinux-related rulesSpecial security policies

Most server firewall configurations primarily use the filter table.

Chains

Chains are ordered lists of rules applied at specific points in packet processing.

Common built-in chains (filter table):

ChainTraffic Type
INPUTPackets destined to the local machine
OUTPUTPackets originating from the local machine
FORWARDPackets routed through the machine

nat table common chains:

ChainTraffic Type
--
PREROUTINGBefore routing decision
POSTROUTINGAfter routing decision
OUTPUTLocally generated packets (NAT)

Policies, Rules, Matches, Targets

  • Policy: default action for a chain if no rule matches (example: DROP)
  • Rule: a line that matches packet attributes and applies an action
  • Match: condition (source, destination, protocol, port, interface, state)
  • Target: action (ACCEPT, DROP, REJECT, LOG, DNAT, SNAT, jump)

Inspecting Existing Rules (Safe Read-Only Commands)

List rules (filter table)

sudo iptables -L

List rules with numeric output (avoid DNS lookups)

sudo iptables -L -n

Show verbose output with packet/byte counters

sudo iptables -L -n -v

Show exact rule syntax (best for backup/recreate)

sudo iptables -S

View NAT rules

sudo iptables -t nat -L -n -v
sudo iptables -t nat -S

Common Match Types

MatchMeaningExample
--
-p tcpTCP protocol-p tcp
--dport 22Destination port--dport 22
-s 203.0.113.10Source IP-s 203.0.113.10
-d 192.0.2.10Destination IP-d 192.0.2.10
-i eth0Incoming interface-i eth0
-o eth0Outgoing interface-o eth0
-m conntrack --ctstateConnection state-m conntrack --ctstate ESTABLISHED,RELATED

Essential Baseline Rules (Typical Server)

These examples are shown for learning and understanding. If you are using UFW, prefer managing policy there to avoid conflicts.

1) Allow established connections

sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

2) Allow loopback

sudo iptables -A INPUT -i lo -j ACCEPT

3) Allow SSH (customize port)

sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

4) Allow HTTP/HTTPS

sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

5) Set default policy (deny inbound)

sudo iptables -P INPUT DROP
sudo iptables -P FORWARD DROP
sudo iptables -P OUTPUT ACCEPT

Logging and Reject vs Drop

Drop

  • silently discards packets
  • reduces feedback to attackers
sudo iptables -A INPUT -p tcp --dport 23 -j DROP

Reject

  • discards and replies (ICMP or TCP RST)
  • useful for clarity and debugging
sudo iptables -A INPUT -p tcp --dport 23 -j REJECT

Log (with rate limiting)

Logging every packet can overwhelm logs. Use rate limiting:

sudo iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "IPTABLES BLOCK: " --log-level 4

Port Allow List and IP Allow List

Allow SSH only from one IP

sudo iptables -A INPUT -p tcp -s 203.0.113.10 --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -j DROP

NAT and Port Forwarding (Common VPS Use)

Enable IP forwarding (temporary)

sudo sysctl -w net.ipv4.ip_forward=1

Persist (example):

echo "net.ipv4.ip_forward=1" | sudo tee /etc/sysctl.d/99-ipforward.conf
sudo sysctl --system

Masquerade (typical outbound NAT)

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Port forwarding (DNAT) example

Forward public port 443 to an internal host:

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to-destination 10.0.0.10:443
sudo iptables -A FORWARD -p tcp -d 10.0.0.10 --dport 443 -j ACCEPT

Persistence (Important)

iptables rules can be lost on reboot unless saved and restored by a persistence mechanism.

Common approaches:

  • iptables-persistent / netfilter-persistent on Debian/Ubuntu
  • systemd unit scripts that restore rules at boot
  • migration to nftables native ruleset for modern systems

Debian/Ubuntu persistence

Install:

sudo apt update
sudo apt install iptables-persistent -y

Save current rules:

sudo netfilter-persistent save

Reload:

sudo netfilter-persistent reload

Common Pitfalls

ProblemCauseFix
--
Locked out over SSHDropped INPUT before allowing SSHAdd SSH allow rule first; use console recovery
Rules appear ignoredAnother firewall tool is managing rulesAvoid mixing with UFW/firewalld unless you know the interaction
* timeouts in tracerouteRouters rate-limit ICMPValidate with TCP traceroute or application tests
NAT not workingIP forwarding disabledEnable net.ipv4.ip_forward=1
Rules lost after rebootNo persistenceInstall persistence or migrate to nftables

Relationship to UFW

UFW is a higher-level interface that writes rules into iptables chains. If you manage firewall policy with UFW, avoid manually editing iptables unless:

  • you are auditing (iptables -S, iptables -L -n -v)
  • you are troubleshooting low-level issues
  • you fully understand the resulting rule interactions

Quick Reference

TaskCommand
--
List rulesiptables -L -n -v
Show rule syntaxiptables -S
List NAT rulesiptables -t nat -L -n -v
Allow SSHiptables -A INPUT -p tcp --dport 22 -j ACCEPT
Set default deny inboundiptables -P INPUT DROP
Save rules (Ubuntu)netfilter-persistent save
Reload rulesnetfilter-persistent reload